﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using LuaInterface;
using Microsoft.Xna.Framework;

namespace ConsoleApplication1
{
    class TestSerializer
    {
        // Type t;
        public TestSerializer(Type type)
        {
            //this.t = type;
        }

        public static string Serialize(PropertyTest item)
        {
            string outstr = item.Name + "={\n";
            //outstr += GetAttribute("Type", item.GetType());
            PropertyInfo[] pi = item.GetType().GetProperties();
            foreach (PropertyInfo p in pi)
            {
                outstr += GetMember(p, item);
            }

            outstr += "}";

            return outstr;
        }

        public static string Serialize(object item)
        {
            string outstr = "={\n";
            outstr += GetAttribute("Type", item.GetType());

            MemberInfo[] properties = item.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty & BindingFlags.SetProperty);
            MemberInfo[] fields = item.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField & BindingFlags.SetField);

            MemberInfo[] members = new MemberInfo[properties.Length + fields.Length];
            properties.CopyTo(members, 0);
            fields.CopyTo(members, properties.Length);

            foreach (MemberInfo p in members)
            {
                outstr += GetMember(p, item);
            }

            outstr += "}";

            return outstr;
        }

        public static string GetMember(MemberInfo minfo, object item)
        {

            if (minfo.MemberType == MemberTypes.Property)
                return GetProperty((PropertyInfo)minfo, item);
            if (minfo.MemberType == MemberTypes.Field)
                return GetField((FieldInfo)minfo, item);
            throw new Exception(minfo.Name + " :is not filed nor property!");
        }

        public static string GetProperty(PropertyInfo pinfo, object item)
        {
            string name = pinfo.Name;
            string _type = pinfo.PropertyType.ToString();
            object value = pinfo.GetValue(item, null);
            string property = name + "={\n" + "Type='" + _type + "';\n" + "Value='" + value + "';\n};\n";
            return property;
        }

        public static string GetField(FieldInfo finfo, object item)
        {
            string name = finfo.Name;
            string _type = finfo.FieldType.ToString();
            object value = finfo.GetValue(item);
            string property = name + "={\n" + "Type='" + _type + "';\n" + "Value='" + value + "';\n};\n";
            return property;
        }

        public static string GetAttribute(string name, object value)
        {

            string _value = value.ToString();
            string attribute = name + "='" + _value + "';\n";
            return attribute;
        }

        public object DeSerialize(LuaInterface.LuaTable table)
        {
            string typeStr = table["Type"].ToString();
            Type type = Type.GetType(typeStr);
            object item = Activator.CreateInstance(type);
            PropertyInfo[] pis = item.GetType().GetProperties();

            foreach (PropertyInfo pi in pis)
            {
                string pName = pi.Name;
                object value = ((LuaTable)table[pName])["Value"];
                setValue(item, pi, value);
            }
            return item;
        }

        private void setValue(object item, PropertyInfo pi, object value)
        {
            if (value != null)
            {
                Type pType = pi.PropertyType;
                object _value = Convert(value.ToString(), pType);
                pi.SetValue(item, _value, null);
            }
        }

        public object Convert(string value, Type type)
        {
            object _out = value;
            if (type == typeof(Vector2)) _out = convertToVector2(value);
            if (type == typeof(Boolean)) _out = Boolean.Parse(value);
            if (type == typeof(float)) _out = Single.Parse(value);
            if (type == typeof(int)) _out = int.Parse(value);
            return _out;
        }

        public Vector2 convertToVector2(string vect)
        {
            string pos = vect;
            int startInd = pos.IndexOf("X:") + 2;
            float aXPosition = float.Parse(pos.Substring(startInd, pos.IndexOf(" Y") - startInd));
            startInd = pos.IndexOf("Y:") + 2;
            float aYPosition = float.Parse(pos.Substring(startInd, pos.IndexOf("}") - startInd));

            Vector2 v = new Vector2(aXPosition, aYPosition);
            return v;
        }


    }
}
